﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace B
{

    //建造者模式简介
    //建造者模式（Builder Pattern）是一种创建型设计模式，它的主要目的是将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。

    //✅ 关键思想：将对象的“创建过程”一步步封装，并且允许构建过程灵活控制、复用、变换顺序和组合方式。

    //适用场景

    //需要构建的对象非常复杂，由多个部分组成（例如HTML页面、房子、餐品等）。
    //构建过程中的各个步骤有顺序要求或者变化多端。
    //希望通过不同的建造器，构建出不同版本的对象（同样的构造过程，得到不同产品）。

    //优点
    //1.封装构建过程：将构建逻辑封装到建造者中，清晰明了
    //2.解耦了产品和构建过程：可以自由更换建造者，灵活构建不同产品。
    //3.支持更复杂的对象创建：比工厂方法更适合“组装式”的对象。

    //案例
    //建造一个“快餐汉堡套餐”


    /// <summary>
    /// 产品类
    /// </summary>
    public class Meal
    {
        public string Burger { get; set; }   //汉堡包
        public string Drink { get; set; }    //饮料
        public string Fries { get; set; }    //薯条

        public void Show()
        {
            Console.WriteLine($"本套餐包含: {Burger}, {Drink}, {Fries}");
        }
    }

    /// <summary>
    /// 抽象建造者
    /// </summary>
    public abstract class AbstractMealBuilder
    {
        //组合一个餐类进来
        protected Meal meal = new Meal();

        public abstract void BuildBurger();
        public abstract void BuildDrink();
        public abstract void BuildFries();

        public Meal GetMeal() => meal;
    }

    //具体建造者（ConcreteBuilder）1

    public class KidsMealBuilder : AbstractMealBuilder
    {
        public override void BuildBurger() => meal.Burger = "小汉堡";
        public override void BuildDrink() => meal.Drink = "果汁";
        public override void BuildFries() => meal.Fries = "小份薯条";
    }

    //具体建造者（ConcreteBuilder）2
    public class AdultMealBuilder : AbstractMealBuilder
    {
        public override void BuildBurger() => meal.Burger = "大汉堡";
        public override void BuildDrink() => meal.Drink = "可乐";
        public override void BuildFries() => meal.Fries = "大份薯条";
    }


    /// <summary>
    /// 指挥者（Director）,可以灵活改变构建过程, 灵活控制、复用、变换顺序和组合方式
    /// </summary>
    public class MealDirector
    {
        public void Construct(AbstractMealBuilder builder)
        {
            builder.BuildBurger();
            builder.BuildDrink();
            builder.BuildFries();
        }

        public void Construct2(AbstractMealBuilder builder)
        {
            builder.BuildDrink();
            builder.BuildBurger();
            builder.BuildFries();
        }

        public void Construct3(AbstractMealBuilder builder)
        {
            builder.BuildDrink();
            builder.BuildBurger();
        }
    }





    /// <summary>
    /// 建造产品
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            func1();
            func2();

            Console.ReadKey();
        }

        static void func1()
        {
            Director director = new Director();
            Product product = director.builder();
            Console.WriteLine(product);
        }

        static void func2()
        {
            MealDirector director = new MealDirector();

            AbstractMealBuilder builder = new KidsMealBuilder();
            director.Construct(builder);
            Meal kidsMeal = builder.GetMeal();
            kidsMeal.Show();

            builder = new AdultMealBuilder();
            director.Construct3(builder);
            Meal adultMeal = builder.GetMeal();
            adultMeal.Show();

            builder = new AdultMealBuilder();
            director.Construct2(builder);
            Meal adultMeal2 = builder.GetMeal();
            adultMeal2.Show();

        }

    }
}
